package org.springblade.common.utils.message;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.message.domain.SendRequest;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.modules.notice.core.event.CallbackEvent;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author ysq
 * @Date 2024/11/18
 * @Description 消息中台工具类
 */
@Component
@Slf4j
public class MessageCenterUtils {

	private final static String APPID_HEADER_KEY = "appid";
	private final static String TIMESTAMP_HEADER_KEY = "timestamp";
	private final static String NONCE_HEADER_KEY = "nonce";
	private final static String SIGNATURE_HEADER_KEY = "signature";
	private final static String APP_SECRET = "secret";
	private static final String SEND_MESSAGE_URL = "/openApi/send/message";
	private static final Integer TIMEOUT = 5000;

	@Value("${message.center.url}")
	private String url;
	@Value("${message.center.appid}")
	private String appid;
	@Value("${message.center.secret}")
	private String secret;

	@Resource
	private ApplicationEventPublisher applicationEventPublisher;

	/**
	 * 发送消息
	 */
	public R sendMessage(SendRequest sendRequest) {
		final String timestamp = String.valueOf(DateUtil.current());
		final String nonce = RandomUtil.randomNumbers(8);
		String sign = generateSignature(timestamp, nonce);
		Map<String, String> headers = new HashMap<>(4);
		headers.put(APPID_HEADER_KEY, appid);
		headers.put(TIMESTAMP_HEADER_KEY, timestamp);
		headers.put(NONCE_HEADER_KEY, nonce);
		headers.put(SIGNATURE_HEADER_KEY, sign);

		HttpResponse res = null;
		try {
			res = HttpRequest.post(url + SEND_MESSAGE_URL).headerMap(headers, true).body(JSONUtil.toJsonStr(sendRequest)).timeout(TIMEOUT).execute();
			R r = JSONUtil.toBean(res.body(), R.class);
			if (r.isSuccess()) {
				log.info("消息中台发送消息成功: param:{}, result:{}", JSONObject.toJSONString(sendRequest), JSONObject.toJSONString(r));
				// 将 r.getData() 转换为 JSONArray
				JSONArray jsonArray = JSONArray.parseArray(r.getData().toString());
				for (Object item : jsonArray) {
					JSONObject dataObj = (JSONObject) item;
					Map<String, Object> callbackData = dataObj.getJSONObject("callback");
					if (callbackData != null) {
						// 发布回调事件
						applicationEventPublisher.publishEvent(new CallbackEvent(this, sendRequest, callbackData));
					}
				}
			} else {
				log.warn("消息中台发送消息失败: param:{}, result:{}", JSONObject.toJSONString(sendRequest), JSONObject.toJSONString(r));
			}
			return r;
		} catch (Exception e) {
			throw new ServiceException("消息中台请求异常! error: " + e.getMessage());
		} finally {
			if (res != null) {
				try {
					res.close();
				} catch (Exception ignored) {}
			}
		}
	}

	/**
	 * 生成签名
	 */
	private String generateSignature(String timestamp, String nonce) {
		Map<String, String> params = new HashMap<>(4);
		params.put(APPID_HEADER_KEY, appid);
		params.put(APP_SECRET, secret);
		params.put(TIMESTAMP_HEADER_KEY, timestamp);
		params.put(NONCE_HEADER_KEY, nonce);
		return SignUtils.createSign(params);
	}
}
